package cn.com.anypay.manager.payment.core;

import cn.com.anypay.manager.payment.config.ChannelConfig;
import cn.com.anypay.manager.payment.dto.PaymentRequestDTO;
import cn.com.anypay.manager.payment.dto.PaymentResultDTO;
import cn.com.anypay.manager.payment.dto.QueryRequestDTO;
import cn.com.anypay.manager.payment.dto.QueryResultDTO;
import cn.com.anypay.manager.payment.factory.PaymentProductFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 抽象支付渠道模板类
 *
 * 实现支付渠道的通用逻辑，具体渠道继承此类实现特定业务逻辑
 * 使用模板方法模式，定义了支付流程的骨架
 *
 * @author AnyPay Team
 * @version 1.0
 * @since 2025-07-05
 */
public abstract class AbstractPaymentChannelTemplate implements IPaymentChannel {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 渠道配置
     */
    protected ChannelConfig channelConfig;

    /**
     * 支付产品工厂 - 不再使用@Autowired，通过setter注入
     */
    protected PaymentProductFactory productFactory;

    /**
     * 初始化状态
     */
    protected final AtomicBoolean initialized = new AtomicBoolean(false);

    /**
     * 渠道版本
     */
    protected static final String DEFAULT_VERSION = "1.0.0";

    public AbstractPaymentChannelTemplate() {
    }

    public AbstractPaymentChannelTemplate(ChannelConfig channelConfig) {
        this.channelConfig = channelConfig;
    }

    @Override
    public String getVersion() {
        return DEFAULT_VERSION;
    }

    @Override
    public boolean isAvailable() {
        return initialized.get() &&
               channelConfig != null &&
               channelConfig.isEnabled() &&
               channelConfig.isValid();
    }

    @Override
    public void initialize() throws PaymentException {
        if (initialized.get()) {
            logger.warn("Channel {} is already initialized", getChannelId());
            return;
        }

        logger.debug("Initializing channel: {}", getChannelId());

        // 验证配置
        if (channelConfig == null) {
            throw new PaymentException("INIT_ERROR", "Channel config is null", getChannelId());
        }

        if (!channelConfig.isValid()) {
            String[] errors = channelConfig.getValidationErrors();
            throw new PaymentException("CONFIG_INVALID",
                "Channel config is invalid: " + String.join(", ", errors), getChannelId());
        }

        // 执行具体的初始化逻辑
        doInitialize();

        initialized.set(true);
        logger.debug("Channel {} initialized successfully", getChannelId());
    }

    @Override
    public void destroy() {
        if (!initialized.get()) {
            return;
        }

        logger.debug("Destroying channel: {}", getChannelId());

        // 执行具体的销毁逻辑
        doDestroy();

        initialized.set(false);
        logger.debug("Channel {} destroyed successfully", getChannelId());
    }

    @Override
    public PaymentResultDTO createPayment(PaymentRequestDTO request) throws PaymentException {
        if (!isAvailable()) {
            throw new PaymentException("CHANNEL_UNAVAILABLE", "Channel is not available", getChannelId());
        }

        if (request == null) {
            throw new PaymentException("INVALID_REQUEST", "Payment request is null", getChannelId());
        }

        logger.debug("Creating payment for channel: {}, orderId: {}", getChannelId(), request.getMerchantOrderId());

        // 验证请求参数
        validatePaymentRequest(request);

        // 执行具体的支付创建逻辑
        PaymentResultDTO result = doCreatePayment(request);

        logger.debug("Payment created successfully for channel: {}, orderId: {}",
            getChannelId(), request.getMerchantOrderId());

        return result;
    }

    @Override
    public QueryResultDTO queryPayment(QueryRequestDTO request) throws PaymentException {
        if (!isAvailable()) {
            throw new PaymentException("CHANNEL_UNAVAILABLE", "Channel is not available", getChannelId());
        }

        if (request == null) {
            throw new PaymentException("INVALID_REQUEST", "Query request is null", getChannelId());
        }

        logger.debug("Querying payment for channel: {}, orderId: {}", getChannelId(), request.getMerchantOrderId());

        // 验证请求参数
        validateQueryRequest(request);

        // 执行具体的查询逻辑
        QueryResultDTO result = doQueryPayment(request);

        logger.debug("Payment queried successfully for channel: {}, orderId: {}",
            getChannelId(), request.getMerchantOrderId());

        return result;
    }

    @Override
    public boolean closePayment(String orderId) throws PaymentException {
        if (!isAvailable()) {
            throw new PaymentException("CHANNEL_UNAVAILABLE", "Channel is not available", getChannelId());
        }

        if (orderId == null || orderId.trim().isEmpty()) {
            throw new PaymentException("INVALID_REQUEST", "Order ID is null or empty", getChannelId());
        }

        logger.debug("Closing payment for channel: {}, orderId: {}", getChannelId(), orderId);

        // 执行具体的关闭逻辑
        boolean result = doClosePayment(orderId);

        logger.debug("Payment closed successfully for channel: {}, orderId: {}", getChannelId(), orderId);

        return result;
    }

    @Override
    public boolean verifyCallback(String data) throws PaymentException {
        if (!isAvailable()) {
            throw new PaymentException("CHANNEL_UNAVAILABLE", "Channel is not available", getChannelId());
        }

        if (data == null || data.trim().isEmpty()) {
            throw new PaymentException("INVALID_REQUEST", "Callback data is null or empty", getChannelId());
        }

        logger.debug("Verifying callback for channel: {}", getChannelId());

        // 执行具体的验证逻辑
        boolean result = doVerifyCallback(data);

        logger.debug("Callback verified successfully for channel: {}", getChannelId());

        return result;
    }

    @Override
    public PaymentResultDTO processCallback(String data) throws PaymentException {
        if (!isAvailable()) {
            throw new PaymentException("CHANNEL_UNAVAILABLE", "Channel is not available", getChannelId());
        }

        if (data == null || data.trim().isEmpty()) {
            throw new PaymentException("INVALID_REQUEST", "Callback data is null or empty", getChannelId());
        }

        logger.debug("Processing callback for channel: {}", getChannelId());

        // 执行具体的处理逻辑
        PaymentResultDTO result = doProcessCallback(data);

        logger.debug("Callback processed successfully for channel: {}", getChannelId());

        return result;
    }

    @Override
    public boolean validateConfig(String config) {
        try {
            // 执行具体的配置验证逻辑
            return doValidateConfig(config);
        } catch (Exception e) {
            logger.error("Failed to validate config for channel: {}", getChannelId(), e);
            return false;
        }
    }

    // ==== 抽象方法，子类必须实现 ====

    /**
     * 执行具体的初始化逻辑
     *
     * @throws PaymentException 初始化失败时抛出
     */
    protected abstract void doInitialize() throws PaymentException;

    /**
     * 执行具体的销毁逻辑
     */
    protected abstract void doDestroy();

    /**
     * 执行具体的支付创建逻辑
     *
     * @param request 支付请求
     * @return 支付结果
     * @throws PaymentException 创建失败时抛出
     */
    protected abstract PaymentResultDTO doCreatePayment(PaymentRequestDTO request) throws PaymentException;

    /**
     * 执行具体的查询逻辑
     *
     * @param request 查询请求
     * @return 查询结果
     * @throws PaymentException 查询失败时抛出
     */
    protected abstract QueryResultDTO doQueryPayment(QueryRequestDTO request) throws PaymentException;

    /**
     * 执行具体的关闭逻辑
     *
     * @param orderId 订单ID
     * @return 关闭结果
     * @throws PaymentException 关闭失败时抛出
     */
    protected abstract boolean doClosePayment(String orderId) throws PaymentException;

    /**
     * 执行具体的回调验证逻辑
     *
     * @param data 回调数据
     * @return 验证结果
     * @throws PaymentException 验证失败时抛出
     */
    protected abstract boolean doVerifyCallback(String data) throws PaymentException;

    /**
     * 执行具体的回调处理逻辑
     *
     * @param data 回调数据
     * @return 处理结果
     * @throws PaymentException 处理失败时抛出
     */
    protected abstract PaymentResultDTO doProcessCallback(String data) throws PaymentException;

    /**
     * 执行具体的配置验证逻辑
     *
     * @param config 配置字符串
     * @return 验证结果
     */
    protected abstract boolean doValidateConfig(String config);

    // ==== 钩子方法，子类可以重写 ====

    /**
     * 验证支付请求参数
     *
     * @param request 支付请求
     * @throws PaymentException 验证失败时抛出
     */
    protected void validatePaymentRequest(PaymentRequestDTO request) throws PaymentException {
        if (request.getMerchantOrderId() == null || request.getMerchantOrderId().trim().isEmpty()) {
            throw new PaymentException("INVALID_REQUEST", "Merchant order ID is null or empty", getChannelId());
        }

        if (request.getAmount() == null || request.getAmount().compareTo(java.math.BigDecimal.ZERO) <= 0) {
            throw new PaymentException("INVALID_REQUEST", "Amount is null or invalid", getChannelId());
        }

        if (request.getSubject() == null || request.getSubject().trim().isEmpty()) {
            throw new PaymentException("INVALID_REQUEST", "Subject is null or empty", getChannelId());
        }
    }

    /**
     * 验证查询请求参数
     *
     * @param request 查询请求
     * @throws PaymentException 验证失败时抛出
     */
    protected void validateQueryRequest(QueryRequestDTO request) throws PaymentException {
        if ((request.getMerchantOrderId() == null || request.getMerchantOrderId().trim().isEmpty()) &&
            (request.getChannelOrderId() == null || request.getChannelOrderId().trim().isEmpty())) {
            throw new PaymentException("INVALID_REQUEST", "Both merchant order ID and channel order ID are null or empty", getChannelId());
        }
    }

    // ==== Getter & Setter ====

    public ChannelConfig getChannelConfig() {
        return channelConfig;
    }

    public void setChannelConfig(ChannelConfig channelConfig) {
        this.channelConfig = channelConfig;
    }

    /**
     * 设置支付产品工厂
     */
    public void setProductFactory(PaymentProductFactory productFactory) {
        this.productFactory = productFactory;
    }

    /**
     * 获取支付产品工厂
     */
    public PaymentProductFactory getProductFactory() {
        return productFactory;
    }

    public boolean isInitialized() {
        return initialized.get();
    }

    // ==== 支付产品管理 ====

    /**
     * 获取支持的支付产品（从ProductFactory动态获取）
     *
     * @return 支付产品列表
     */
    @Override
    public String[] getSupportedPayProducts() {
        return getSupportedPayProductsFromFactory();
    }

    /**
     * 从ProductFactory获取支持的支付产品
     *
     * @return 支付产品列表
     */
    protected String[] getSupportedPayProductsFromFactory() {
        if (productFactory == null) {
            logger.warn("ProductFactory未初始化，返回空数组 - 渠道: {}", getChannelId());
            return new String[0];
        }

        // 从ProductFactory动态获取
        String[] products = productFactory.getSupportedProductTypes(getChannelId());
        logger.debug("渠道 {} 支持的支付产品: {}", getChannelId(), java.util.Arrays.toString(products));
        return products;
    }
}